﻿/*
 * MIT License
 *Copyright (c) 2021 易开元(Easy-Open-Meta)

 *Permission is hereby granted, free of charge, to any person obtaining a copy
 *of this software and associated documentation files (the "Software"), to deal
 *in the Software without restriction, including without limitation the rights
 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *copies of the Software, and to permit persons to whom the Software is
 *furnished to do so, subject to the following conditions:

 *The above copyright notice and this permission notice shall be included in all
 *copies or substantial portions of the Software.

 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *SOFTWARE.
 *
 */
using EOM.TSHotelManagement.Common.Contract;
using EOM.TSHotelManagement.Common.Core;
using EOM.TSHotelManagement.Common.Util;
using EOM.TSHotelManagement.EntityFramework;
using EOM.TSHotelManagement.Shared;
using jvncorelib.CodeLib;
using jvncorelib.EntityLib;
using SqlSugar;
using System.Transactions;

namespace EOM.TSHotelManagement.Application
{
    /// <summary>
    /// 客房信息接口实现类
    /// </summary>
    public class RoomService : IRoomService
    {
        /// <summary>
        /// 客房信息
        /// </summary>
        private readonly GenericRepository<Room> roomRepository;

        /// <summary>
        /// 消费记录
        /// </summary>
        private readonly GenericRepository<Spend> spendRepository;

        /// <summary>
        /// 客房类型
        /// </summary>
        private readonly GenericRepository<RoomType> roomTypeRepository;

        /// <summary>
        /// 能耗管理
        /// </summary>
        private readonly GenericRepository<EnergyManagement> energyRepository;

        /// <summary>
        /// 客户信息
        /// </summary>
        private readonly GenericRepository<Customer> custoRepository;

        /// <summary>
        /// 客户类型
        /// </summary>
        private readonly GenericRepository<CustoType> custoTypeRepository;

        /// <summary>
        /// 会员等级规则
        /// </summary>
        private readonly GenericRepository<VipLevelRule> vipLevelRuleRepository;

        /// <summary>
        /// 预约信息
        /// </summary>
        private readonly GenericRepository<Reser> reserRepository;

        /// <summary>
        /// 唯一编码
        /// </summary>
        private readonly UniqueCode uniqueCode;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="roomRepository"></param>
        /// <param name="spendRepository"></param>
        /// <param name="roomTypeRepository"></param>
        /// <param name="energyRepository"></param>
        /// <param name="custoRepository"></param>
        /// <param name="custoTypeRepository"></param>
        /// <param name="vipLevelRuleRepository"></param>
        /// <param name="reserRepository"></param>
        /// <param name="uniqueCode"></param>
        public RoomService(GenericRepository<Room> roomRepository, GenericRepository<Spend> spendRepository, GenericRepository<RoomType> roomTypeRepository, GenericRepository<EnergyManagement> energyRepository, GenericRepository<Customer> custoRepository, GenericRepository<CustoType> custoTypeRepository, GenericRepository<VipLevelRule> vipLevelRuleRepository, GenericRepository<Reser> reserRepository, UniqueCode uniqueCode)
        {
            this.roomRepository = roomRepository;
            this.spendRepository = spendRepository;
            this.roomTypeRepository = roomTypeRepository;
            this.energyRepository = energyRepository;
            this.custoRepository = custoRepository;
            this.custoTypeRepository = custoTypeRepository;
            this.vipLevelRuleRepository = vipLevelRuleRepository;
            this.reserRepository = reserRepository;
            this.uniqueCode = uniqueCode;
        }

        /// <summary>
        /// 根据房间状态获取相应状态的房间信息
        /// </summary>
        /// <param name="readRoomInputDto"></param>
        /// <returns></returns>
        public ListOutputDto<ReadRoomOutputDto> SelectRoomByRoomState(ReadRoomInputDto readRoomInputDto)
        {
            var where = Expressionable.Create<Room>();

            if (!readRoomInputDto.IsDelete.IsNullOrEmpty())
            {
                where = where.And(a => a.IsDelete == readRoomInputDto.IsDelete);
            }
            if (readRoomInputDto.RoomStateId > 0)
            {
                where = where.And(a => a.RoomStateId == readRoomInputDto.RoomStateId);
            }

            var count = 0;
            List<Room> rooms = new List<Room>();

            if (!readRoomInputDto.IgnorePaging && readRoomInputDto.Page != 0 && readRoomInputDto.PageSize != 0)
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readRoomInputDto.Page, readRoomInputDto.PageSize, ref count);
            }
            else
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToList();
                count = rooms.Count;
            }

            var result = EntityMapper.MapList<Room, ReadRoomOutputDto>(rooms);

            return new ListOutputDto<ReadRoomOutputDto>
            {
                Data = new PagedData<ReadRoomOutputDto>
                {
                    Items = result,
                    TotalCount = count
                }
            };
        }

        /// <summary>
        /// 根据房间状态来查询可使用的房间
        /// </summary>
        /// <returns></returns>
        public ListOutputDto<ReadRoomOutputDto> SelectCanUseRoomAll()
        {
            var rooms = roomRepository.GetList(a => a.RoomStateId == (int)RoomState.Vacant);
            var result = EntityMapper.MapList<Room, ReadRoomOutputDto>(rooms);
            return new ListOutputDto<ReadRoomOutputDto>
            {
                Data = new PagedData<ReadRoomOutputDto>
                {
                    Items = result,
                    TotalCount = result.Count
                }
            };
        }

        /// <summary>
        /// 获取所有房间信息
        /// </summary>
        /// <returns></returns>
        public ListOutputDto<ReadRoomOutputDto> SelectRoomAll(ReadRoomInputDto readRoomInputDto)
        {
            var where = Expressionable.Create<Room>();

            if (!readRoomInputDto.IsDelete.IsNullOrEmpty())
            {
                where = where.And(a => a.IsDelete == readRoomInputDto.IsDelete);
            }

            var count = 0;
            List<Room> rooms = new List<Room>();

            if (!readRoomInputDto.IgnorePaging && readRoomInputDto.Page != 0 && readRoomInputDto.PageSize != 0)
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readRoomInputDto.Page, readRoomInputDto.PageSize, ref count);
            }
            else
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToList();
                count = rooms.Count;
            }

            var result = EntityMapper.MapList<Room, ReadRoomOutputDto>(rooms);
            var roomTypes = roomTypeRepository.AsQueryable().Where(a => a.IsDelete != 1).ToList();
            foreach (var item in result)
            {
                var helper = new EnumHelper();
                var roomStates = Enum.GetValues(typeof(RoomState))
                    .Cast<RoomState>()
                    .Select(e => new EnumDto
                    {
                        Id = (int)e,
                        Name = e.ToString(),
                        Description = helper.GetEnumDescription(e)
                    })
                    .ToList();
                item.RoomState = roomStates.Where(a => a.Id == item.RoomStateId).Single().Description;
                var roomType = roomTypes.Single(a => a.RoomTypeId == item.RoomTypeId);
                item.RoomName = roomType.RoomTypeName;
            }
            return new ListOutputDto<ReadRoomOutputDto>
            {
                Data = new PagedData<ReadRoomOutputDto>
                {
                    Items = result,
                    TotalCount = count
                }
            };
        }

        /// <summary>
        /// 获取房间分区的信息
        /// </summary>
        /// <returns></returns>
        public ListOutputDto<ReadRoomOutputDto> SelectRoomByTypeName(ReadRoomInputDto readRoomInputDto)
        {
            var where = Expressionable.Create<Room>();

            if (!readRoomInputDto.RoomTypeName.IsNullOrEmpty())
            {
                var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeName == readRoomInputDto.RoomTypeName);
                where = where.And(a => a.RoomTypeId == roomType.RoomTypeId);
            }

            var count = 0;
            List<Room> rooms = new List<Room>();

            if (!readRoomInputDto.IgnorePaging && readRoomInputDto.Page != 0 && readRoomInputDto.PageSize != 0)
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToPageList(readRoomInputDto.Page, readRoomInputDto.PageSize, ref count);
            }
            else
            {
                rooms = roomRepository.AsQueryable().Where(where.ToExpression()).ToList();
                count = rooms.Count;
            }

            var result = EntityMapper.MapList<Room, ReadRoomOutputDto>(rooms);

            return new ListOutputDto<ReadRoomOutputDto>
            {
                Data = new PagedData<ReadRoomOutputDto>
                {
                    Items = result,
                    TotalCount = count
                }
            };
        }

        /// <summary>
        /// 根据房间编号查询房间信息
        /// </summary>
        /// <param name="readRoomInputDto"></param>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> SelectRoomByRoomNo(ReadRoomInputDto readRoomInputDto)
        {
            List<EnumDto> roomStates = new List<EnumDto>();
            var helper = new EnumHelper();
            roomStates = Enum.GetValues(typeof(RoomState))
            .Cast<RoomState>()
            .Select(e => new EnumDto
            {
                Id = (int)e,
                Name = e.ToString(),
                Description = helper.GetEnumDescription(e)
            })
            .ToList();
            Room room = new Room();
            room = roomRepository.GetFirst(a => a.IsDelete != 1 && a.RoomNumber == readRoomInputDto.RoomNumber);
            if (!room.IsNullOrEmpty())
            {
                var roomSate = roomStates.SingleOrDefault(a => a.Id == room.RoomStateId);
                room.RoomState = roomSate.Description.IsNullOrEmpty() ? "" : roomSate.Description;
                var roomType = roomTypeRepository.GetFirst(a => a.RoomTypeId == room.RoomTypeId);
                room.RoomName = roomType.RoomTypeName.IsNullOrEmpty() ? "" : roomType.RoomTypeName;
            }
            else
            {
                room = new Room();
            }

            var Data = EntityMapper.Map<Room, ReadRoomOutputDto>(room);

            return new SingleOutputDto<ReadRoomOutputDto>() { Data = Data };
        }

        /// <summary>
        /// 根据房间编号查询截止到今天住了多少天
        /// </summary>
        /// <param name="roomInputDto"></param>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> DayByRoomNo(ReadRoomInputDto roomInputDto)
        {
            var room = roomRepository.GetFirst(a => a.RoomNumber == roomInputDto.RoomNumber);
            if (room?.LastCheckInTime != null)
            {
                var days = Math.Abs((room.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue) - DateTime.Now).Days);
                return new SingleOutputDto<ReadRoomOutputDto> { Data = new ReadRoomOutputDto { StayDays = days } };
            }
            return new SingleOutputDto<ReadRoomOutputDto> { Data = new ReadRoomOutputDto { StayDays = 0 } };
        }

        /// <summary>
        /// 根据房间编号修改房间信息（入住）
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public BaseResponse UpdateRoomInfo(UpdateRoomInputDto r)
        {
            try
            {
                roomRepository.Update(new Room()
                {
                    Id = r.Id,
                    RoomNumber = r.RoomNumber,
                    LastCheckInTime = r.LastCheckInTime,
                    RoomStateId = r.RoomStateId,
                    CustomerNumber = r.CustomerNumber,
                    DataChgDate = r.DataChgDate,
                    DataChgUsr = r.DataChgUsr,
                });
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 根据房间编号修改房间信息（预约）
        /// </summary>
        /// <param name="r"></param>
        /// <returns></returns>
        public BaseResponse UpdateRoomInfoWithReser(UpdateRoomInputDto r)
        {
            try
            {
                roomRepository.Update(new Room()
                {
                    Id = r.Id,
                    RoomNumber = r.RoomNumber,
                    RoomStateId = r.RoomStateId,
                    DataChgUsr = r.DataChgUsr,
                    DataInsDate = r.DataInsDate,
                });
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>  
        /// 查询可入住房间数量  
        /// </summary>  
        /// <returns></returns>  
        public SingleOutputDto<ReadRoomOutputDto> SelectCanUseRoomAllByRoomState()
        {
            try
            {
                var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Vacant && a.IsDelete != 1);
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Data = new ReadRoomOutputDto { Vacant = count }
                };
            }
            catch (Exception ex)
            {
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
                    Code = BusinessStatusCode.InternalServerError
                };
            }
        }

        /// <summary>
        /// 查询已入住房间数量
        /// </summary>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> SelectNotUseRoomAllByRoomState()
        {
            try
            {
                var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Occupied && a.IsDelete != 1);
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Data = new ReadRoomOutputDto { Occupied = count }
                };
            }
            catch (Exception ex)
            {
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
                    Code = BusinessStatusCode.InternalServerError
                };
            }
        }

        /// <summary>
        /// 根据房间编号查询房间价格
        /// </summary>
        /// <returns></returns>
        public object SelectRoomByRoomPrice(ReadRoomInputDto r)
        {
            return roomRepository.GetFirst(a => a.RoomNumber == r.RoomNumber).RoomRent;
        }

        /// <summary>
        /// 查询脏房数量
        /// </summary>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> SelectNotClearRoomAllByRoomState()
        {
            try
            {
                var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Dirty && a.IsDelete != 1);
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Data = new ReadRoomOutputDto { Dirty = count }
                };
            }
            catch (Exception ex)
            {
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
                    Code = BusinessStatusCode.InternalServerError
                };
            }
        }

        /// <summary>
        /// 查询维修房数量
        /// </summary>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> SelectFixingRoomAllByRoomState()
        {
            try
            {
                var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Maintenance && a.IsDelete != 1);
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Data = new ReadRoomOutputDto { Maintenance = count }
                };
            }
            catch (Exception ex)
            {
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
                    Code = BusinessStatusCode.InternalServerError
                };
            }
        }

        /// <summary>
        /// 查询预约房数量
        /// </summary>
        /// <returns></returns>
        public SingleOutputDto<ReadRoomOutputDto> SelectReservedRoomAllByRoomState()
        {
            try
            {
                var count = roomRepository.Count(a => a.RoomStateId == (int)RoomState.Reserved && a.IsDelete != 1);
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Data = new ReadRoomOutputDto { Reserved = count }
                };
            }
            catch (Exception ex)
            {
                return new SingleOutputDto<ReadRoomOutputDto>
                {
                    Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message),
                    Code = BusinessStatusCode.InternalServerError
                };
            }
        }

        /// <summary>
        /// 根据房间编号更改房间状态
        /// </summary>
        /// <param name="updateRoomInputDto"></param>
        /// <returns></returns>
        public BaseResponse UpdateRoomStateByRoomNo(UpdateRoomInputDto updateRoomInputDto)
        {
            try
            {
                var room = roomRepository.GetFirst(a => a.RoomNumber == updateRoomInputDto.RoomNumber);
                roomRepository.Update(new Room()
                {
                    Id = room.Id,
                    RoomNumber = room.RoomNumber,
                    RoomStateId = updateRoomInputDto.RoomStateId
                });
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 添加房间
        /// </summary>
        /// <param name="rn"></param>
        /// <returns></returns>
        public BaseResponse InsertRoom(CreateRoomInputDto rn)
        {
            try
            {
                var isExist = roomRepository.IsAny(a => a.RoomNumber == rn.RoomNumber && a.IsDelete != 1);
                if (isExist)
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room already exists.", "房间已存在。"), Code = BusinessStatusCode.InternalServerError };

                var entity = EntityMapper.Map<CreateRoomInputDto, Room>(rn);
                entity.LastCheckInTime = DateOnly.MinValue;
                entity.LastCheckOutTime = DateOnly.MinValue;
                var result = roomRepository.Insert(entity);
                if (!result)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to add room.", "添加房间失败。"), Code = BusinessStatusCode.InternalServerError };
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }

            return new BaseResponse();
        }

        /// <summary>
        /// 更新房间
        /// </summary>
        /// <param name="rn"></param>
        /// <returns></returns>
        public BaseResponse UpdateRoom(UpdateRoomInputDto rn)
        {
            try
            {
                var isExist = roomRepository.IsAny(a => a.RoomNumber == rn.RoomNumber);
                if (!isExist)
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room does not exist.", "房间不存在。"), Code = BusinessStatusCode.InternalServerError };

                var entity = EntityMapper.Map<UpdateRoomInputDto, Room>(rn);
                var result = roomRepository.Update(entity);
                if (!result)
                {
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to update room.", "更新房间失败。"), Code = BusinessStatusCode.InternalServerError };
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }

            return new BaseResponse();
        }

        /// <summary>
        /// 删除房间
        /// </summary>
        /// <param name="rn"></param>
        /// <returns></returns>
        public BaseResponse DeleteRoom(DeleteRoomInputDto rn)
        {
            try
            {
                var isExist = roomRepository.IsAny(a => a.RoomNumber == rn.RoomNumber);
                if (!isExist)
                    return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("This room does not exist.", "房间不存在。"), Code = BusinessStatusCode.InternalServerError };
                roomRepository.Update(EntityMapper.Map<DeleteRoomInputDto, Room>(rn));
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }

            return new BaseResponse();
        }

        /// <summary>
        /// 转房操作
        /// </summary>
        /// <param name="transferRoomDto"></param>
        /// <returns></returns>
        public BaseResponse TransferRoom(TransferRoomDto transferRoomDto)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    var customer = custoRepository.GetFirst(a => a.CustomerNumber == transferRoomDto.CustomerNumber && a.IsDelete != 1);
                    if (customer.IsNullOrEmpty())
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not exist", "客户不存在"), Code = BusinessStatusCode.InternalServerError };

                    var originalSpends = spendRepository.GetList(a => a.RoomNumber == transferRoomDto.OriginalRoomNumber
                        && a.CustomerNumber == transferRoomDto.CustomerNumber && a.SettlementStatus == ConsumptionConstant.UnSettle.Code
                        && a.IsDelete == 0).ToList();

                    var vipRules = vipLevelRuleRepository.GetList(a => a.IsDelete != 1).ToList();

                    var originalRoom = roomRepository.GetFirst(a => a.RoomNumber == transferRoomDto.OriginalRoomNumber);
                    if (originalRoom.CustomerNumber != transferRoomDto.CustomerNumber)
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not match the original room", "客户与原房间不匹配"), Code = BusinessStatusCode.InternalServerError };

                    if (!originalRoom.LastCheckInTime.HasValue)
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The original room lacks check-in time", "原房间缺少入住时间"), Code = BusinessStatusCode.InternalServerError };

                    var targetRoom = roomRepository.GetFirst(a => a.RoomNumber == transferRoomDto.TargetRoomNumber);
                    if (targetRoom.IsNullOrEmpty())
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The room does not exist", "房间不存在"), Code = BusinessStatusCode.InternalServerError };
                    if (targetRoom.RoomStateId != (int)RoomState.Vacant)
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The room is not vacant", "房间不处于空房状态"), Code = BusinessStatusCode.InternalServerError };

                    var staySpan = DateTime.Now - originalRoom.LastCheckInTime.Value.ToDateTime(TimeOnly.MinValue);
                    var stayDays = Math.Max((int)Math.Ceiling(staySpan.TotalDays), 1);

                    var originalSpendNumbers = originalSpends.Select(a => a.SpendNumber).ToList();
                    var TotalCountSpent = originalSpends.Sum(a => a.ConsumptionAmount);

                    var newLevelId = vipRules
                            .Where(vipRule => TotalCountSpent >= vipRule.RuleValue)
                            .OrderByDescending(vipRule => vipRule.RuleValue)
                            .ThenByDescending(vipRule => vipRule.VipLevelId)
                            .FirstOrDefault()?.VipLevelId ?? 0;

                    if (newLevelId != 0)
                    {
                        custoRepository.Update(a => new Customer
                        {
                            CustomerType = newLevelId,
                            DataChgUsr = transferRoomDto.DataChgUsr,
                            DataChgDate = DateTime.Now
                        }, a => a.CustomerNumber == transferRoomDto.CustomerNumber);
                    }

                    var customerType = custoTypeRepository.GetFirst(a => a.CustomerType == customer.CustomerType);
                    if (customerType.IsNullOrEmpty())
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer type does not exist", "客户类型不存在"), Code = BusinessStatusCode.InternalServerError };

                    decimal discountFactor = customerType.Discount / 100M;
                    decimal originalRoomBill = originalRoom.RoomRent * stayDays * discountFactor;

                    //更新目标房间状态
                    roomRepository.Update(new Room
                    {
                        Id = targetRoom.Id,
                        RoomNumber = targetRoom.RoomNumber,
                        CustomerNumber = originalRoom.CustomerNumber,
                        LastCheckInTime = DateOnly.FromDateTime(DateTime.Now),
                        RoomStateId = (int)RoomState.Occupied,
                        DataChgDate = transferRoomDto.DataChgDate,
                        DataChgUsr = transferRoomDto.DataChgUsr
                    });

                    //更新原房间状态
                    roomRepository.Update(new Room
                    {
                        Id = originalRoom.Id,
                        RoomNumber = originalRoom.RoomNumber,
                        CustomerNumber = string.Empty,
                        LastCheckInTime = DateOnly.MinValue,
                        LastCheckOutTime = DateOnly.FromDateTime(DateTime.Now),
                        RoomStateId = (int)RoomState.Dirty,
                        DataChgDate = transferRoomDto.DataChgDate,
                        DataChgUsr = transferRoomDto.DataChgUsr
                    });

                    //转移原房间消费记录
                    if (originalSpendNumbers.Count > 0)
                    {
                        var originalSpendList = spendRepository.AsQueryable().Where(a => originalSpendNumbers.Contains(a.SpendNumber)).ToList();
                        var spends = new List<Spend>();

                        foreach (var spend in originalSpendList)
                        {
                            spend.SpendNumber = spend.SpendNumber;
                            spend.RoomNumber = transferRoomDto.TargetRoomNumber;
                        }

                        spendRepository.UpdateRange(spends);
                    }

                    //添加旧房间消费记录
                    var originalSpend = new Spend
                    {
                        CustomerNumber = originalRoom.CustomerNumber,
                        RoomNumber = transferRoomDto.TargetRoomNumber,
                        SpendNumber = uniqueCode.GetNewId("SP-"),
                        ProductNumber = transferRoomDto.OriginalRoomNumber,
                        ProductName = "居住" + transferRoomDto.OriginalRoomNumber + "共" + stayDays + "天",
                        ProductPrice = originalRoom.RoomRent,
                        ConsumptionTime = DateTime.Now,
                        SettlementStatus = ConsumptionConstant.UnSettle.Code,
                        ConsumptionQuantity = stayDays,
                        ConsumptionAmount = originalRoomBill,
                        ConsumptionType = SpendType.Room.Code,
                        IsDelete = 0,
                        DataInsDate = transferRoomDto.DataChgDate,
                        DataInsUsr = transferRoomDto.DataChgUsr
                    };
                    spendRepository.Insert(originalSpend);

                    scope.Complete();

                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 退房操作
        /// </summary>
        /// <param name="checkoutRoomDto"></param>
        /// <returns></returns>
        public BaseResponse CheckoutRoom(CheckoutRoomDto checkoutRoomDto)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    var customer = custoRepository.AsQueryable().Where(a => a.CustomerNumber == checkoutRoomDto.CustomerNumber && a.IsDelete != 1);
                    if (!customer.Any())
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("The customer does not exist", "客户不存在"), Code = BusinessStatusCode.InternalServerError };

                    var room = roomRepository.GetFirst(a => a.RoomNumber == checkoutRoomDto.RoomNumber);
                    //更新房间状态
                    roomRepository.Update(new Room
                    {
                        Id = room.Id,
                        RoomNumber = room.RoomNumber,
                        CustomerNumber = null,
                        LastCheckInTime = DateOnly.MinValue,
                        LastCheckOutTime = DateOnly.FromDateTime(DateTime.Now),
                        RoomStateId = (int)RoomState.Dirty,
                        DataChgDate = checkoutRoomDto.DataChgDate,
                        DataChgUsr = checkoutRoomDto.DataChgUsr
                    });

                    //添加能源使用记录
                    var energy = new EnergyManagement
                    {
                        InformationId = uniqueCode.GetNewId("EM-"),
                        StartDate = (DateOnly)room.LastCheckInTime,
                        EndDate = DateOnly.FromDateTime((DateTime)checkoutRoomDto.DataChgDate),
                        WaterUsage = checkoutRoomDto.WaterUsage,
                        PowerUsage = checkoutRoomDto.ElectricityUsage,
                        Recorder = checkoutRoomDto.DataChgUsr,
                        CustomerNumber = room.CustomerNumber,
                        RoomNumber = checkoutRoomDto.RoomNumber,
                        IsDelete = 0,
                        DataInsDate = checkoutRoomDto.DataChgDate,
                        DataInsUsr = checkoutRoomDto.DataChgUsr
                    };
                    energyRepository.Insert(energy);

                    //结算消费记录
                    var spendNumbers = spendRepository.GetList(a => a.RoomNumber == checkoutRoomDto.RoomNumber
                        && a.CustomerNumber.Equals(checkoutRoomDto.CustomerNumber) && a.SettlementStatus.Equals(ConsumptionConstant.UnSettle)
                        && a.IsDelete == 0).ToList();
                    if (spendNumbers.Count > 0)
                    {
                        var spends = new List<Spend>();
                        foreach (var spend in spendNumbers)
                        {
                            spends.Add(new Spend
                            {
                                SpendNumber = spend.SpendNumber,
                                RoomNumber = checkoutRoomDto.RoomNumber,
                                CustomerNumber = checkoutRoomDto.CustomerNumber,
                                ProductName = spend.ProductName,
                                ProductPrice = spend.ProductPrice,
                                ConsumptionQuantity = spend.ConsumptionQuantity,
                                ConsumptionAmount = spend.ConsumptionAmount,
                                ConsumptionTime = DateTime.Now,
                                SettlementStatus = ConsumptionConstant.Settled.Code,
                                ConsumptionType = spend.ConsumptionType,
                                IsDelete = 0,
                                DataInsDate = checkoutRoomDto.DataChgDate,
                                DataInsUsr = checkoutRoomDto.DataChgUsr
                            });
                        }

                        spendRepository.UpdateRange(spends);
                    }

                    scope.Complete();
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }

        /// <summary>
        /// 根据预约信息办理入住
        /// </summary>
        /// <param name="checkinRoomByReservationDto"></param>
        /// <returns></returns>
        public BaseResponse CheckinRoomByReservation(CheckinRoomByReservationDto checkinRoomByReservationDto)
        {
            try
            {
                using (TransactionScope scope = new TransactionScope())
                {
                    var customer = new Customer
                    {
                        CustomerNumber = checkinRoomByReservationDto.CustomerNumber,
                        CustomerName = checkinRoomByReservationDto.CustomerName,
                        CustomerGender = checkinRoomByReservationDto.CustomerGender,
                        CustomerPhoneNumber = checkinRoomByReservationDto.CustomerPhoneNumber,
                        PassportId = checkinRoomByReservationDto.PassportId,
                        IdCardNumber = checkinRoomByReservationDto.IdCardNumber,
                        CustomerAddress = checkinRoomByReservationDto.CustomerAddress,
                        DateOfBirth = checkinRoomByReservationDto.DateOfBirth,
                        CustomerType = checkinRoomByReservationDto.CustomerType,
                        IsDelete = 0,
                        DataInsUsr = checkinRoomByReservationDto.DataInsUsr,
                        DataInsDate = checkinRoomByReservationDto.DataInsDate
                    };
                    var customerResult = custoRepository.Insert(customer);
                    if (!customerResult)
                    {
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to add customer.", "添加客户失败。"), Code = BusinessStatusCode.InternalServerError };
                    }

                    var room = roomRepository.GetFirst(a => a.RoomNumber == checkinRoomByReservationDto.RoomNumber && a.IsDelete != 1);
                    var roomUpdateResult = roomRepository.Update(new Room()
                    {
                        RoomNumber = room.RoomNumber,
                        Id = room.Id,
                        LastCheckInTime = DateOnly.FromDateTime(DateTime.Now),
                        CustomerNumber = customer.CustomerNumber,
                        RoomStateId = new EnumHelper().GetEnumValue(RoomState.Occupied),
                        DataChgDate = checkinRoomByReservationDto.DataChgDate,
                        DataChgUsr = checkinRoomByReservationDto.DataChgUsr
                    });

                    if (!roomUpdateResult)
                    {
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to update room.", "更新房间失败。"), Code = BusinessStatusCode.InternalServerError };
                    }

                    var reser = reserRepository.GetFirst(a => a.ReservationId == checkinRoomByReservationDto.ReservationId && a.IsDelete != 1);
                    var reserUpdateResult = reserRepository.Update(new Reser
                    {
                        ReservationId = reser.ReservationId,
                        Id = reser.Id,
                        IsDelete = 1,
                        DataChgUsr = checkinRoomByReservationDto.DataChgUsr,
                        DataChgDate = checkinRoomByReservationDto.DataChgDate
                    });

                    if (!reserUpdateResult)
                    {
                        return new BaseResponse { Message = LocalizationHelper.GetLocalizedString("Failed to update reservation.", "更新预约失败。"), Code = BusinessStatusCode.InternalServerError };
                    }

                    scope.Complete();
                }
            }
            catch (Exception ex)
            {
                return new BaseResponse { Message = LocalizationHelper.GetLocalizedString(ex.Message, ex.Message), Code = BusinessStatusCode.InternalServerError };
            }
            return new BaseResponse();
        }
    }
}
